package org.springframework.beans.factory.support;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanDefinition;

import javax.xml.stream.events.ProcessingInstruction;
import java.lang.reflect.Method;

/**
 * @Name DisposableBeanAdapter
 * @Description: DisposableBean 接口 [适配器] 实现类
 * @Version v1.0.0
 * @Author: lichao
 * @Date: 2024-03-20 15:25:39
 **/
public class DisposableBeanAdapter implements DisposableBean {
    private final Object bean;
    private final String beanName;
    private final String destroyMethodName;

    public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) {
        this.bean = bean;
        this.beanName = beanName;
        this.destroyMethodName = beanDefinition.getDestoryMethodName();
    }

    @Override
    public void destory() throws Exception {
        // 1. 执行实现了 DisposableBean 接口的销毁方法
        if (bean instanceof DisposableBean) {
            ((DisposableBean) bean).destory();
        }
        // 2. 执行在 Xml 配置文件中制定了 Bean 自定义的销毁方法
        // 条件: 避免同时继承自 DisposableBean，且自定义方法与 DisposableBean 方法同名，销毁方法执行两次的情况
        // 即: 既实现了 DisposableBean 接口, 又同时在 Xml 配置文件中指定了该销毁方法的情况
        if (StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean && "destory".equals(this.destroyMethodName))) {
            Method destoryMethod = ClassUtil.getPublicMethod(bean.getClass(), destroyMethodName);
            if (destoryMethod == null)
                throw new BeansException("Bean [" + beanName + "] 中没有发现名称为 '" + destroyMethodName + "' 的销毁方法");
            destoryMethod.invoke(bean);
        }
    }
}

